﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.Diagnostics;
using System.Xml;
using System.IO;

namespace D6.DFS.DevUtility
{

    #region MainForm

    public enum ResultsView
    {
        DataGrid,
        XML,
        PlainText,
    }

    public partial class MainForm : Form
    {
        private Stopwatch stopWatch = null;
        private DataTable dqlResultSet = null;
        private XmlDocument xmlResultSet = null;
        private StringBuilder strResultSet = null;
        private ResultsView viewResultsAs = ResultsView.DataGrid;

        public MainForm()
        {
            InitializeComponent();
            stopWatch = new Stopwatch();
            dqlResultSet = new DataTable("QueryResults");
            xmlResultSet = new XmlDocument();
            strResultSet = new StringBuilder();
            statementTimer = new Timer();
            statementTimer.Tick += new EventHandler(statementTimer_Tick);
            statementTimer.Enabled = true;
            statementTimer.Interval = 1;
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConnectionForm connForm = new ConnectionForm(this);
            connForm.ShowDialog();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        public void AddDfsConnection(int dfsKey)
        {
            if (dfsKey < -1)
            {
                return;
            }

            schemaRepositories.DfsRepositoryInfoRow dfsRow = AppWideData.Instance.DfsUrls[dfsKey];

            TreeNode dfsNode = new TreeNode();
            dfsNode.Tag = dfsRow.DfsKey;
            dfsNode.Text = dfsRow.Repository;

            DfsRepositoryInfo dfsInfo = new DfsRepositoryInfo(dfsRow.Username, dfsRow.Password, dfsRow.Repository);
            dfsInfo.SetDfsUrl(dfsRow.DFSURL);
            stopWatch.Reset();
            stopWatch.Start();
            dfsInfo.GetTypeInfo();
            stopWatch.Stop();

            if (!String.IsNullOrEmpty(dfsInfo.ErrorMessage))
            {
                MessageBox.Show(dfsInfo.ErrorMessage, "Documentum Development Utility Error!");
                return;
            }

            TreeNode typeNode = null;

            for (int i = 0; i < AppWideData.Instance.CurrentKeyList.Count; i++)
            {
                typeNode = new TreeNode();
                schemaRepositories.DocumentumTypeInfoRow typeInfo = AppWideData.Instance.DocumentumTypes[i];
                typeNode.Tag = typeInfo.TypeKey;
                typeNode.Text = typeInfo.Name;
                dfsNode.Nodes.Add(typeNode);
            }

            _connTreeView.Nodes["Repositories"].Nodes.Add(dfsNode);


        }

        private void executeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            dqlResultSet = new DataTable();
            xmlResultSet = new XmlDocument();
            strResultSet = new StringBuilder();
            string dqlQueries = null;
            dqlQueries = dqlQueryArea.SelectedText;
            if (String.IsNullOrEmpty(dqlQueries))
            {
                dqlQueries = dqlQueryArea.Text;
            }
            int currRepositoryIndex = AppWideData.Instance.CurrentDfsKey;
            schemaRepositories.DfsRepositoryInfoRow repositoryInfo = AppWideData.Instance.DfsUrls[currRepositoryIndex];
            DqlQueryHandler dqlHandler = new DqlQueryHandler(repositoryInfo.Repository, repositoryInfo.Username, repositoryInfo.Password, dqlResultSet, xmlResultSet, strResultSet);
            stopWatch.Reset();
            stopWatch.Start();
            dqlHandler.ExecuteDQL(dqlQueries);
            stopWatch.Stop();
            dqlResultsGrid.DataSource = dqlResultSet;

            if (viewResultsAs == ResultsView.DataGrid)
            {
                dqlResultsGrid.Dock = DockStyle.Fill;
                dqlResultsGrid.Visible = true;
                resultsTextBox.Visible = false;
            }
            else if (viewResultsAs == ResultsView.PlainText)
            {
                resultsTextBox.Dock = DockStyle.Fill;
                resultsTextBox.Visible = true;
                dqlResultsGrid.Visible = false;
                resultsTextBox.Text = strResultSet.ToString();
            }
            else if (viewResultsAs == ResultsView.XML)
            {
                resultsTextBox.Dock = DockStyle.Fill;
                resultsTextBox.Visible = true;
                resultsTextBox.Text = xmlResultSet.InnerXml;
                dqlResultsGrid.Visible = false;
            }

        }

        private void statementTimer_Tick(object sender, EventArgs e)
        {
            stopwatchDisplay.Text = stopWatch.ElapsedMilliseconds + " ms";
        }

        private void dataGridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            viewResultsAs = ResultsView.DataGrid;
            xMLToolStripMenuItem.Checked = false;
            plainTextToolStripMenuItem.Checked = false;
            dqlResultsGrid.Dock = DockStyle.Fill;
            dqlResultsGrid.Visible = true;
            resultsTextBox.Visible = false;
        }

        private void xMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            viewResultsAs = ResultsView.XML;
            dataGridToolStripMenuItem.Checked = false;
            plainTextToolStripMenuItem.Checked = false;
            dqlResultsGrid.Visible = false;
            resultsTextBox.Text = xmlResultSet.InnerXml;
            resultsTextBox.Dock = DockStyle.Fill;
            resultsTextBox.Visible = true;
        }

        private void plainTextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            viewResultsAs = ResultsView.PlainText;
            dataGridToolStripMenuItem.Checked = false;
            xMLToolStripMenuItem.Checked = false;
            dqlResultsGrid.Visible = false;
            resultsTextBox.Text = strResultSet.ToString();
            resultsTextBox.Dock = DockStyle.Fill;
            resultsTextBox.Visible = true;
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveScriptDialog.FileOk += new CancelEventHandler(saveScriptDialog_FileOk);
            saveScriptDialog.ShowDialog();
        }

        private void saveScriptDialog_FileOk(object sender, CancelEventArgs e)
        {
            string dqlText = dqlQueryArea.Text;
            if (String.IsNullOrWhiteSpace(dqlText))
            {
                MessageBox.Show("There is no DQL to save!", "Documentum Development Utility");
                return;
            }
            string dqlScriptFile = saveScriptDialog.FileName;
            if (String.IsNullOrWhiteSpace(dqlScriptFile))
            {
                return;
            }

            try
            {
                FileStream fs = new FileStream(dqlScriptFile, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine(dqlText);
                sw.Flush();
                sw.Close();
            }
            catch (IOException ioex)
            {
                MessageBox.Show(ioex.ToString(), "Documentum Development Utility");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Documentum Development Utility");
            }

        }
    }

    #endregion MainForm


    #region Get initial info

    class DfsRepositoryInfo : D6.DFS.Consumer.DfsConsumer
    {

        private const string _getTypesDql = "select * from dm_type where super_name = 'dm_document';";

        public void GetTypeInfo()
        {
            ExecuteDQL(_getTypesDql);
        }

        public DfsRepositoryInfo(string username, string password, string repository)
            : base(repository, username, password)
        {
            //SetCurrentRepository(repository, username, password);
        }

        public void SetDfsUrl(string dfsUrl)
        {
            if (String.IsNullOrEmpty(dfsUrl))
            {
                return;
            }

            if (m_queryService == null)
            {
                return;
            }

            EndpointAddress endpointAddress = new EndpointAddress(dfsUrl);
            m_queryService.Endpoint.Address = endpointAddress;

        }



        protected override void processQueryResults(D6QueryService.QueryResult repositoryItems)
        {

            foreach (D6QueryService.DataObject attr in repositoryItems.dataPackage.DataObjects)
            {
                D6QueryService.PropertySet attrPropertySet = attr.Properties;
                D6QueryService.Property objectId = attrPropertySet.Properties[0];
                D6QueryService.StringProperty strObjectId = (D6QueryService.StringProperty)objectId;
                //mmsUrl = strArrayProperty.Values[0];
                D6QueryService.Property typeNameProperty = attrPropertySet.Properties[1];
                D6QueryService.StringProperty strTypeName = (D6QueryService.StringProperty)typeNameProperty;
                schemaRepositories.DocumentumTypeInfoRow typeRow = AppWideData.Instance.DocumentumTypes.NewDocumentumTypeInfoRow();
                typeRow.ObjectID = strObjectId.Value;
                typeRow.Name = strTypeName.Value;
                AppWideData.Instance.DocumentumTypes.AddDocumentumTypeInfoRow(typeRow);
                AppWideData.Instance.CurrentKeyList.Add(typeRow.TypeKey);

            }
        }

        public TreeNode GetDocumentumRepositoryInfo(TreeNode dctmRootNode)
        {
            if (dctmRootNode == null)
            {
                return null;
            }

            ExecuteDQL(_getTypesDql);


            return null;

        }

    }


    #endregion Get initial info


#region DQL Query Handling - for DataSet, XML, text

    public class DqlQueryHandler : DFS.Consumer.DfsConsumer
    {

        private DataTable dqlResultSet = null;
        private XmlDocument xmlResultSet = null;
        private StringBuilder strResultSet = null;
        private const int _fieldSize = 30;

        public DqlQueryHandler(string repository, string username, string password, DataTable _dqlResultSet, XmlDocument _xmlResultSet, StringBuilder _strResultSet)
            : base(repository, username, password)
        {
            dqlResultSet = _dqlResultSet;
            xmlResultSet = _xmlResultSet;
            strResultSet = _strResultSet;
        }

        protected override void processQueryResults(D6QueryService.QueryResult repositoryItems)
        {
            //return;

            int totalResults = repositoryItems.dataPackage.DataObjects.Count();
            XmlElement rootNode = xmlResultSet.CreateElement("Results");

            if (totalResults > 0)
            {
                D6QueryService.DataObject attr1 = repositoryItems.dataPackage.DataObjects[0];
                int totalColumns = attr1.Properties.Properties.Count();

                if (totalColumns > 1)
                {
                    string[] results = new string[totalColumns];
                    D6QueryService.PropertySet resultRow = attr1.Properties;

                    DataColumn keyColumn = new DataColumn("RecordNumber");
                    //keyColumn.DataType = Type.GetType("System.Int32");
                    //keyColumn.AutoIncrement = true;
                    //keyColumn.AutoIncrementSeed = -1;
                    //keyColumn.AutoIncrementStep = 1;
                    dqlResultSet.Columns.Add(keyColumn);

                    XmlElement record0 = xmlResultSet.CreateElement(attr1.type);
                    XmlAttribute recordNum = xmlResultSet.CreateAttribute("RecordNumber");
                    recordNum.Value = "0";
                    record0.Attributes.Append(recordNum);
                    strResultSet.Append(writeField("RecordNumber", _fieldSize));

                    for (int i = 0; i < totalColumns; i++)
                    {
                        D6QueryService.Property property = resultRow.Properties[i];
                        DataColumn col = new DataColumn(property.name);
                        XmlElement propertyNode = xmlResultSet.CreateElement(property.name);
                        strResultSet.Append(writeField(property.name, _fieldSize));

                        if (property is D6QueryService.StringProperty)
                        {
                            results[i] = ((D6QueryService.StringProperty)property).Value;
                        }
                        else if (property is D6QueryService.NumberProperty)
                        {
                            results[i] = ((D6QueryService.NumberProperty)property).Item.ToString();
                        }
                        propertyNode.InnerText = results[i];
                        (record0 as XmlElement).AppendChild(propertyNode);                        
                        dqlResultSet.Columns.Add(col);
                    }
                    strResultSet.Append("\n");

                    //add first row to DataTable:
                    DataRow row = dqlResultSet.NewRow();
                    row.SetField<Int32>("RecordNumber", 0);
                    strResultSet.Append(writeField("0", _fieldSize));
                    for (int i = 0; i < totalColumns; i++)
                    {
                        row.SetField<string>(i+1, results[i]);
                        strResultSet.Append(writeField(results[i], _fieldSize));
                    }
                    dqlResultSet.Rows.Add(row);
                    rootNode.AppendChild(record0);
                    strResultSet.Append("\n");
                    for (int i = 0; i < totalColumns * _fieldSize; i++)
                    {
                        strResultSet.Append("-");
                    }
                    strResultSet.Append("\n");

                    //add remaining rows
                    for (int i = 1; i < totalResults; i++)
                    {
                        D6QueryService.DataObject attr = repositoryItems.dataPackage.DataObjects[i];
                        resultRow = attr.Properties;
                        row = dqlResultSet.NewRow();
                        XmlElement resultRecord = xmlResultSet.CreateElement(attr.type);
                        row.SetField<Int32>("RecordNumber", i);
                        XmlAttribute recordNumber = xmlResultSet.CreateAttribute("RecordNumber");
                        recordNumber.Value = i.ToString();
                        resultRecord.Attributes.Append(recordNumber);
                        strResultSet.Append(writeField(i.ToString(), _fieldSize));

                        for (int j = 0; j < totalColumns; j++)
                        {
                            D6QueryService.Property property = resultRow.Properties[j];
                            XmlElement propertyElement = xmlResultSet.CreateElement(property.name);

                            if (property is D6QueryService.StringProperty)
                            {
                                row.SetField<string>(j+1, (property as D6QueryService.StringProperty).Value);
                                propertyElement.InnerText = (property as D6QueryService.StringProperty).Value;
                            }
                            else if (property is D6QueryService.NumberProperty)
                            {
                                row.SetField<string>(j+1, (property as D6QueryService.NumberProperty).Item.ToString());
                                propertyElement.InnerText = (property as D6QueryService.NumberProperty).Item.ToString();
                            }
                            resultRecord.AppendChild(propertyElement);
                            strResultSet.Append(writeField(row.Field<string>(j + 1), _fieldSize));
                        }
                        dqlResultSet.Rows.Add(row);
                        rootNode.AppendChild(resultRecord);
                        strResultSet.Append("\n");
                    }

                    xmlResultSet.AppendChild(rootNode);

                }

            }

        }

        protected string writeField(string txt, int fieldSize)
        {
            if (fieldSize < 1)
            {
                return String.Empty;
            }

            string columnStr = null;
            if (String.IsNullOrEmpty(txt))
            {
                for (int i = 0; i < fieldSize; i++)
                {
                    columnStr += " ";
                }
                return columnStr;
            }

            int txtSize = txt.Length;
            int paddedSpace = fieldSize - txtSize;
            if (txtSize > _fieldSize)
            {
                columnStr = txt.Substring(0, fieldSize);
            }
            else
            {
                columnStr = txt;
            }

            if (paddedSpace > 0)
            {
                for (int i = 0; i < paddedSpace; i++)
                {
                    columnStr += " ";
                }
            }

            return columnStr;
                
        }

    }


#endregion DQL Query Handling - for DataSet, XML, text


}
